﻿using System;
using System.Collections.Generic;
using System.Text;
using SMBL.Interface.Database;
using Oracle.DataAccess.Client;
using System.Data;


namespace SMBL.ADBS.Providers
{
    class ORACLE : IDBProvider
    {
        //////////////////////////////////////////////////////////////////////////
        // Parameters
        //////////////////////////////////////////////////////////////////////////

        // Global Connection String
        private String myConnectionString;
        // Connection statue
        private Boolean beConnected = false;
        public Boolean HasConnected
        {
            get { return beConnected; }
        }
        // Connection
        private OracleConnection oracleConn;
        // Command
        private OracleCommand oracleCmd;

        //////////////////////////////////////////////////////////////////////////
        // Interface
        //////////////////////////////////////////////////////////////////////////

        #region IAProvider 成员

        public bool Lock()
        {
            //throw new NotImplementedException();
            return true;
        }

        public bool Lock(int TimeOut)
        {
            //throw new NotImplementedException();
            return true;
        }

        public void UnLock()
        {
            //throw new NotImplementedException();
            return;
        }

        #endregion

        #region IStart 成员

        public bool Start()
        {
            // Check if current provider has connected to the database
            if (this.beConnected) return true;
            // Create the connection
            this.oracleConn = new OracleConnection(myConnectionString);
            // on error throw any exception
            // will be caught by ErrorSystem
            this.oracleConn.Open();
            this.beConnected = true;
            this.oracleCmd = new OracleCommand();
            this.oracleCmd.Connection = this.oracleConn;
            return true;
        }

        #endregion

        #region IEnd 成员

        public bool End()
        {
            if (!this.beConnected) return true;
            // Release the connection
            this.oracleCmd.Dispose();
            this.oracleConn.Dispose();
            this.oracleConn.Close();
            this.beConnected = false;

            return true;
        }

        #endregion

        #region IProducer 成员

        public System.Data.DataSet Producer(string ProducerName)
        {
            // Create the command and set command type as stored procedure
            oracleCmd.CommandText = ProducerName;
            oracleCmd.CommandType = CommandType.StoredProcedure;
            // Use Adapter
            OracleDataAdapter tmpAdapter = new OracleDataAdapter(oracleCmd);
            DataSet rtnDataSet = new DataSet();
            // Fill the DataSet
            tmpAdapter.Fill(rtnDataSet);

            // Reset
            oracleCmd.CommandType = CommandType.Text;
            return rtnDataSet;
        }

        public System.Data.DataSet Producer(string ProducerName, List<KeyValuePair<string, object>> ParameterValue)
        {
            // Create the command and set command type as stored procedure
            oracleCmd.CommandText = ProducerName;
            oracleCmd.CommandType = CommandType.StoredProcedure;

            // Fill up the parameters
            for (int i = 0; i < ParameterValue.Count; ++i)
            {
                KeyValuePair<String, Object> tmpPair = ParameterValue[i];
                OracleParameter tmpParam = new OracleParameter(tmpPair.Key, tmpPair.Value);
                oracleCmd.Parameters.Add(tmpParam);
            }

            // Use Adapter
            OracleDataAdapter tmpAdapter = new OracleDataAdapter(oracleCmd);
            DataSet rtnDataSet = new DataSet();
            // Fill the DataSet
            tmpAdapter.Fill(rtnDataSet);

            // Reset
            oracleCmd.CommandType = CommandType.Text;
            return rtnDataSet;
        }

        #endregion

        #region IDBBasic 成员

        public int Execute(ISql theSql)
        {
            oracleCmd.CommandText = theSql.GetSql();
            return oracleCmd.ExecuteNonQuery();
        }

        public System.Data.DataSet Query(ISql theSql)
        {
            // Use SqlDataAdapter to execute the query
            OracleDataAdapter tmpAdapter = new OracleDataAdapter(theSql.GetSql(), this.oracleConn);
            DataSet rtnDataSet = new DataSet();
            // Fill the dataset
            tmpAdapter.Fill(rtnDataSet);
            return rtnDataSet;
        }

        #endregion

        #region IAutoUpdate 成员

        public bool AutoUpdate(System.Data.DataTable dataTable)
        {
            throw new NotImplementedException();
        }

        #endregion

        #region ITransaction 成员

        public bool Transaction(delDoTransaction DelegateTransaction)
        {
            // Bind the transaction
            OracleTransaction transAction = oracleConn.BeginTransaction();
            //oracleCmd.Transaction = transAction;

            try
            {
                // Do the methods
                DelegateTransaction();
                transAction.Commit();
            }
            catch (System.Exception e)
            {
                // Error!
                transAction.Rollback();
                // Throw this exception and let cc to get
                throw e;
            }

            return true;
        }

        #endregion

        #region IConnectString 成员

        public void SetConnectionString(string TheConnString)
        {
            // Current Provider has connected to the database correctly
            if (this.beConnected) return;

            this.myConnectionString = TheConnString;
        }

        #endregion
    }
}
